package com.briup.hdfs;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.apache.hadoop.hdfs.client.HdfsDataInputStream;
import org.apache.hadoop.hdfs.protocol.LocatedBlock;
import org.junit.Test;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.List;

public class HdfsStudy {
    // 第一种构建方式
    @Test
    public void createFSOne(){
        // 构建配置
        Configuration config = new Configuration();
        // 指定HDFS的地址
        config.set("fs.defaultFS","hdfs://192.168.10.11:9000");
        try {
            // 构建FileSystem对象，访问各种文件系统的钥匙
            FileSystem fs = FileSystem.get(config);
            System.out.println(fs.getClass());

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    // 第二种构建方式
    @Test
    public void createFSTwo(){
        // 构建配置
        Configuration config = new Configuration();
        // 构建FileSystem对象
        try {
            FileSystem fs = FileSystem.get(
                    new URI("hdfs://192.168.10.11:9000"),
                    config);
            System.out.println(fs.getClass());
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }

    }
    // 第三种构建方式
    @Test
    public void createFSThree(){
        // 构建配置
        Configuration config = new Configuration();
        config.set("fs.defaultFS","hdfs://192.168.10.11:9000");

        // 通过反射构建FileSystem对象
        try {
            FileSystem fs = FileSystem.newInstance(config);
            System.out.println(fs.getClass());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    // 第四种构建方式
    @Test
    public void createFSFour(){
        // 构建配置
        Configuration config = new Configuration();
        // 构建FileSystem对象
        try {
            // file:///
            FileSystem fs = FileSystem.newInstance(
//                    new URI("hdfs://192.168.10.11:9000"),
                    new URI("file:///E:/bigdata/java_project/hadoopstudy/src/main/java/com/hdfs/FirstHadoop.java"),
                    config);
            System.out.println(fs.getClass());
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }
    }
    @Test
    public void readHdfsFile(){
        // 构建配置
        Configuration config = new Configuration();
        config.set("fs.defaultFS","hdfs://192.168.10.11:9000");

        try {
            // 构建FileSystem对象
            FileSystem fs = FileSystem.get(config);
            // 构建路径
            Path path = new Path("/data/data.txt");
            // 使用open方法读文件
            FSDataInputStream fis = fs.open(path);
            BufferedReader br = new BufferedReader(
                    new InputStreamReader(fis));
            String str = "";
            while ((str=br.readLine())!=null){
                System.out.println(str);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    @Test
    public void writeHdfsFile(){
        // 构建配置
        Configuration config = new Configuration();
        config.set("fs.defaultFS","hdfs://192.168.10.11:9000");
        FSDataOutputStream fos = null;
        PrintWriter pw = null;
        try {
            FileSystem fs = FileSystem.get(config);
            // 构建路径,
            Path path = new Path("/newdata/hello.txt");
            // 写文件,通过create方法去写,第二个参数：文件不存在的时候去创建
            // 默认为true
            fos = fs.create(path,true);
            pw = new PrintWriter(fos);
            pw.println("hello world");
            pw.println(1);
            pw.println("aaa");
            // 刷新缓存
            pw.flush();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally{
            try {
                // 关闭流，从下往上关
                if (pw != null) pw.close();
                if (fos != null) fos.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
    // 列出块信息
    @Test
    public void listBlockData(){
        Configuration config = new Configuration();
        config.set("fs.defaultFS","hdfs://192.168.10.11:9000");
        try {
            FileSystem fs = FileSystem.get(config);
            Path path = new Path("/data/data.txt");
            // 读取块信息
            HdfsDataInputStream hdis =
                    (HdfsDataInputStream) fs.open(path);
            // 追溯源类
            System.out.println(hdis.getWrappedStream());
            // 获取到所有的块信息
            List<LocatedBlock> datas = hdis.getAllBlocks();
            for(LocatedBlock data:datas){
                System.out.println(
                        "块id: "+data.getBlock().getBlockId());
                System.out.println(
                        "块的名字: "+data.getBlock().getBlockName());
                System.out.println(
                        "块的大小: "+data.getBlock().getNumBytes());
                System.out.println(
                        "块的位置: "+Arrays.toString(data.getLocations()));
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    // 列出具体元数据信息
    @Test
    public void listDFSData(){
        Configuration config = new Configuration();
        config.set("fs.defaultFS","hdfs://192.168.10.11:9000");
        try {
             FileSystem fs = FileSystem.get(config);
//             Path path = new Path("/data/data.txt");
             // 列出具体的元数据信息
//             FileStatus[] datas = fs.listStatus(path);
//             System.out.println(Arrays.toString(datas));
            // 创建目录
            Path dir = new Path("/one");
//            fs.mkdirs(dir);
            // 判断目录或者文件是否存在，删除目录，
            // delete第二个参数代表递归删除
            if(fs.exists(dir)) fs.delete(dir,true);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }



}
